﻿using Furion.CMS.Core;
using Furion.CMS.Core.EventSource;
using Furion.CMS.Core.Handlers;
using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.EventBus;
using Furion.TaskScheduler;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace Furion.CMS.Domain
{
    public class RolePermissionFormatHandler : AuditLogFormatHandler
    {
        public override string GetRowKey(DbContext context, object entityValues, params string[] formatArgs)
        {
            if (entityValues is PropertyValues values)
            {
                var rid = values.GetValue<int>(nameof(RolePermission.RoleId));
                var permissionCode = values.GetValue<string>(nameof(RolePermission.PermissionCode));
                var role = context.Find<RoleInfo>(rid);
                if (role == null) return "未知";
                var permission = context.Find<PermissionInfo>(permissionCode);

                return $"{role.Name}配置-{permission?.Name}";
            }
            return "未知";
        }

        public override string[] GetChangeValue(DbContext context, object oldValue, object newValue)
        {
            var oldUser = context.Find<PermissionInfo>(oldValue);
            var newUser = context.Find<PermissionInfo>(newValue);

            return new string[2] { oldUser?.Name ?? "无", newUser?.Name ?? "无" };
        }
    }

    /// <summary>
    /// 角色权限
    /// </summary>
    [OperateRecord("角色权限")]
    public class RolePermission : IEntity,
        IEntityTypeBuilder<RolePermission>,
        IEntityChangedListener<RolePermission>
    {
        /// <summary>
        /// 角色id
        /// </summary>
        [OperateRecord("角色id", true, typeof(RolePermissionFormatHandler))]
        public int RoleId { get; set; }
        /// <summary>
        /// 角色信息
        /// </summary>
        public virtual RoleInfo Role { get; set; }

        /// <summary>
        /// 权限代码
        /// </summary>
        [MaxLength(200), Required]
        [OperateRecord("权限代码")]
        public string PermissionCode { get; set; }
        /// <summary>
        /// 权限信息
        /// </summary>
        public virtual PermissionInfo Permission { get; set; }

        public void Configure(EntityTypeBuilder<RolePermission> entityBuilder, DbContext dbContext, Type dbContextLocator)
        {
            entityBuilder.UseDefaultTableNameDefine();

            entityBuilder.HasIndex(i => new { i.RoleId, i.PermissionCode });
        }

        public void OnChanged(RolePermission newEntity, RolePermission oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state)
        {
            SpareTime.DoIt(() =>
            {
                Scoped.Create((_, scope) =>
                {
                    var services = scope.ServiceProvider;
                    // 获取数据库上下文
                    var dbContext = Db.GetDbContext(services);

                    var operationType = CacheOperationType.Add;
                    if (state == EntityState.Detached)
                    {// 移除
                        operationType = CacheOperationType.Remove;
                    }
                    // 触发事件
                    var eventPublisher = services.GetService<IEventPublisher>();
                    // 补充查询角色信息
                    newEntity.Role = newEntity.Role ?? dbContext.Find<RoleInfo>(newEntity.RoleId);
                    // 补充权限信息
                    newEntity.Permission = newEntity.Permission ?? dbContext.Find<PermissionInfo>(newEntity.PermissionCode);
                    dbContext.Attach(newEntity.Role).Collection(c => c.Users).Load();

                    var changeEvents = new List<OnPermissionDataItemChange>();
                    // 获取当前角色变更模块
                    var changeModuleKey = string.Format(CacheKeyConsts.PermissionModule, newEntity.Role.Code);
                    var modulePayload = new string[] { newEntity.PermissionCode };
                    changeEvents.Add(new OnPermissionDataItemChange(operationType, changeModuleKey, modulePayload));
                    // 获取当前角色变更模块的权限依赖
                    if (!string.IsNullOrWhiteSpace(newEntity.Permission.DependentResources))
                    {
                        var dependentResList = newEntity.Permission.DependentResources.Split(new String[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                        var resourcePayload = newEntity.Role.Users.Select(s => string.Format(CacheKeyConsts.PermissionResourceValue, newEntity.Role.Code, s.Id));
                        changeEvents.AddRange(dependentResList.Select(s => new OnPermissionDataItemChange(operationType, string.Format(CacheKeyConsts.PermissionResource, s, ""), resourcePayload)));
                    }

                    eventPublisher?.PublishAsync(new ChannelEventSource(EventIdConsts.PermissionDataItemManyChange, changeEvents));
                });
            });
        }
    }
}
